package com.lucky.common.util;

import org.apache.tools.ant.Project;
import org.apache.tools.ant.taskdefs.Zip;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.zip.ZipEntry;
import org.apache.tools.zip.ZipOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.util.List;
import java.util.zip.CRC32;
import java.util.zip.CheckedOutputStream;
import java.util.zip.ZipInputStream;

public class ZipUtil {
	private static final Logger logger = LoggerFactory.getLogger(ZipUtil.class);
	private static final int BUFFER = 8192;

	/**
	 * 第一种zip压缩方式<br />
	 * 用ant中的org.apache.tools.ant.taskdefs.Zip来实现
	 * 
	 * @param srcPathName
	 *            源文件（夹）
	 * @param zipName
	 *            zip文件名
	 */
	public static void compress(String srcPathName, String zipName) {
		File srcdir = new File(srcPathName);
		if (!srcdir.exists()) {
			logger.error(srcPathName + "not exist！");
			throw new RuntimeException(srcPathName + "not exist！");
		}
		File zipFile = new File(zipName);
		Project prj = new Project();
		Zip zip = new Zip();
		zip.setProject(prj);
		zip.setDestFile(zipFile);
		FileSet fileSet = new FileSet();
		fileSet.setProject(prj);
		fileSet.setDir(srcdir);
		// fileSet.setIncludes("**/*.java"); 包括哪些文件或文件夹
		// eg:zip.setIncludes("*.java");
		// fileSet.setExcludes(...); 排除哪些文件或文件夹
		zip.addFileset(fileSet);

		zip.execute();
	}

	/**
	 * 第二种压缩方式<br />
	 * 由于java.util.zip.ZipOutputStream有中文乱码问题，
	 * 所以采用org.apache.tools.zip.ZipOutputStream。
	 * 
	 * @param srcPathName
	 *            源文件（夹）
	 * @param zipName
	 *            zip文件名
	 */
	public static void compress2(String srcPathName, String zipName) {
		File file = new File(srcPathName);
		if (!file.exists())
			throw new RuntimeException(srcPathName + "不存在！");
		try {
			FileOutputStream fileOutputStream = new FileOutputStream(zipName);
			CheckedOutputStream cos = new CheckedOutputStream(fileOutputStream,
					new CRC32());
			ZipOutputStream out = new ZipOutputStream(cos);
			String basedir = "";
			compress(file, out, basedir);
			out.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	private static void compress(File file, ZipOutputStream out, String basedir) {
		/* 判断是目录还是文件 */
		if (file.isDirectory()) {
			logger.debug("compress：" + basedir + file.getName());
			compressDirectory(file, out, basedir);
		} else {
			logger.debug("compress：" + basedir + file.getName());
			compressFile(file, out, basedir);
		}
	}

	/** 压缩一个目录 */
	private static void compressDirectory(File dir, ZipOutputStream out,
			String basedir) {
		if (!dir.exists())
			return;

		File[] files = dir.listFiles();
		for (int i = 0; i < files.length; i++) {
			/* 递归 */
			compress(files[i], out, basedir + dir.getName() + "/");
		}
	}

	/** 压缩一个文件 */
	private static void compressFile(File file, ZipOutputStream out,
			String basedir) {
		if (!file.exists()) {
			return;
		}
		try {
			BufferedInputStream bis = new BufferedInputStream(
					new FileInputStream(file));
			ZipEntry entry = new ZipEntry(basedir + file.getName());
			out.putNextEntry(entry);
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = bis.read(data, 0, BUFFER)) != -1) {
				out.write(data, 0, count);
			}
			bis.close();
		} catch (Exception e) {
			throw new RuntimeException(e);
		}
	}

	/**
	 * 打包压缩文件
	 * 
	 * @param request
	 * @param response
	 * @param filenames
	 *            所要压缩的源文件名称
	 * @param showfiles
	 *            所要展示的文件名称列表(压缩完之后,压缩包里面的文件名称)
	 * @throws Exception
	 */
	public static File zipFile(String[] filenames, String[] showfiles,
			String filename) throws Exception {
		byte[] buffer = new byte[8192];
		File f = new File(filename);// 生成的临时压缩包文件
		ZipOutputStream out = null;
		try {
			out = new ZipOutputStream(new FileOutputStream(filename));
			out.setEncoding("gbk"); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < filenames.length; i++) {
				File file = new File(filenames[i] + ".xls");
				if (!file.exists()) {
					logger.error("file:" + file.getName() + "not exist, compress fail！");
					throw new Exception("file:" + file.getName() + "not exist, compress fail！");
				}

				FileInputStream fis = new FileInputStream(file);
				out.putNextEntry(new ZipEntry(showfiles[i] + ".xls")); // 包内文件名称
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist,compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
		return f;
	}
	/**
	 * 打包压缩文件
	 * 
	 * @param request
	 * @param response
	 * @param filenames
	 *            所要压缩的源文件名称
	 * @param showfiles
	 *            所要展示的文件名称列表(压缩完之后,压缩包里面的文件名称)
	 * @throws Exception
	 */
	public static File zipFile(List<String> filenames, List<String> showfiles,
			String filename) throws Exception {
		byte[] buffer = new byte[8192];
		File f = new File(filename);// 生成的临时压缩包文件
		if(!f.exists()) {
			f.createNewFile();
		}
		ZipOutputStream out = null;
		try {
			out = new ZipOutputStream(new FileOutputStream(filename));
			out.setEncoding("gbk"); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < filenames.size(); i++) {
				File file = new File(filenames.get(i) + ".xls");
				if (!file.exists()) {
					logger.error("file" + file.getName() + "not exist,compress fail！");
					throw new Exception("文件" + file.getName() + "不存在,打包失败！");
				}

				FileInputStream fis = new FileInputStream(file);
				out.putNextEntry(new ZipEntry(showfiles.get(i) + ".xls")); // 包内文件名称
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist, compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
		return f;
	}
	
	
	
	
	
	public static File zipFile1(List<String> filenames, List<String> showfiles,
			String filename) throws Exception {
		byte[] buffer = new byte[8192];
		File f = new File(filename);// 生成的临时压缩包文件
		if(!f.exists()) {
			f.createNewFile();
		}else {
			f.delete();
			f.createNewFile();
		}
		ZipOutputStream out = null;
		try {
			out = new ZipOutputStream(new FileOutputStream(filename));
			out.setEncoding("gbk"); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < filenames.size(); i++) {
				File file = new File(filenames.get(i));
				if (!file.exists()) {
					logger.error("file" + file.getName() + "not exist,compress fail！");
					throw new Exception("文件" + file.getName() + "不存在,打包失败！");
				}

				FileInputStream fis = new FileInputStream(file);
				out.putNextEntry(new ZipEntry(showfiles.get(i))); // 包内文件名称
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist, compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
		return f;
	}
	
	
	
	
	
	
	
	
	public static String CHARSET_GBK="gbk";
	public static File create(String filename,List<String> srcList, List<String> showList,String charset) throws Exception {
		byte[] buffer = new byte[8192];
		File f = new File(filename);// 生成的临时压缩包文件
		ZipOutputStream out = null;
		try {
			out = new ZipOutputStream(new FileOutputStream(filename));
			out.setEncoding(charset); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < srcList.size(); i++) {
				File file = new File(srcList.get(i));
				if (!file.exists()) {
					logger.error("file" + file.getName() + "not exist,compress fail！");
					throw new Exception("文件" + file.getName() + "不存在,打包失败！");
				}

				FileInputStream fis = new FileInputStream(file);
				out.putNextEntry(new ZipEntry(showList.get(i))); // 包内文件名称
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist, compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
		return f;
	}
	/**
	 * 下载临时压缩文件
	 * 
	 * @param request
	 * @param response
	 * @param filenames
	 *            所要压缩的源文件名称
	 * @param showfiles
	 *            所要展示的文件名称列表(压缩完之后,压缩包里面的文件名称)
	 * @throws Exception
	 */
	public static void downZipFile(HttpServletRequest request,
			HttpServletResponse response, String[] filenames,
			String[] showfiles, String filename) throws Exception {
		byte[] buffer = new byte[8192];
		ZipOutputStream out = null;
		try {
			String agent = request.getHeader("User-Agent");
			boolean isMSIE = (agent != null && agent.toLowerCase().indexOf(
					"windows") != -1);
			if (isMSIE) {
				filename = new String(filename.getBytes("GBK"), "ISO-8859-1");
			} else {
				filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
			}
			response.setContentType("application/x-msdownload");// 设置response内容的类型
			response.setHeader("Content-disposition", "attachment;filename="
					+ filename);// 设置头部信息
			OutputStream outs = response.getOutputStream();// 获取文件输出IO流

			out = new ZipOutputStream(outs);
			out.setEncoding("gbk"); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < filenames.length; i++) {
				File file = new File(filenames[i] + ".xls");
				if (!file.exists()) {
					logger.error("file:" + file.getName() + " not exist, compress fail！");
					throw new Exception("文件" + file.getName() + "不存在,打包失败！");
				}

				FileInputStream fis = new FileInputStream(file);
				out.putNextEntry(new ZipEntry(showfiles[i] + ".xls")); // 包内文件名称
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist, compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
	}
	
	
	
	
	public static void downZipFile1(HttpServletRequest request,
			HttpServletResponse response, String[] filenames,
			String[] showfiles, String filename,String type) throws Exception {
		byte[] buffer = new byte[8192];
		ZipOutputStream out = null;
		try {
			String agent = request.getHeader("User-Agent");
			boolean isMSIE = (agent != null && agent.toLowerCase().indexOf(
					"windows") != -1);
			if (isMSIE) {
				filename = new String(filename.getBytes("GBK"), "ISO-8859-1");
			} else {
				filename = new String(filename.getBytes("UTF-8"), "ISO-8859-1");
			}
			response.setContentType("application/x-msdownload");// 设置response内容的类型
			response.setHeader("Content-disposition", "attachment;filename="
					+ filename);// 设置头部信息
			OutputStream outs = response.getOutputStream();// 获取文件输出IO流

			out = new ZipOutputStream(outs);
			out.setEncoding("gbk"); // 设置压缩文件内的字符编码，防止出现乱码
			for (int i = 0; i < filenames.length; i++) {
				File file = new File(filenames[i] );
				if (!file.exists()) {
					logger.error("file:" + file.getName() + " not exist, compress fail！");
					throw new Exception("文件" + file.getName() + "不存在,打包失败！");
				}

				FileInputStream fis = new FileInputStream(file);
				
				
//				out.putNextEntry(new ZipEntry(showfiles[i] + ".xls")); // 包内文件名称  type
				out.putNextEntry(new ZipEntry(showfiles[i] + type));
				int len;
				// 读入需要下载的文件的内容，打包到zip文件
				while ((len = fis.read(buffer)) > 0) {
					out.write(buffer, 0, len);
				}
				out.closeEntry();
				fis.close();
			}
		} catch (FileNotFoundException e) {
			logger.error("file not exist, compress fail！",e);
			throw new Exception("文件不存在,打包失败！");
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
		}
	}
	
	
	
	
	
	
	
	
	
	
	/**
	 * 将压缩文件解压到指定的文件目录下
	 * @param filePath 解压文件目录
	 * @param path 解压后文件存放路径
	 * @param folderName 保存解压后文件夹名称
	 * @throws IOException
	 */
	public static void unZip(String filePath, String path,String folderName) throws IOException {
		ZipInputStream inputStream = new ZipInputStream(new FileInputStream(
				filePath));
		java.util.zip.ZipEntry zipEntry = null;
		FileOutputStream outputStream = null;
		String lockPath = path;
		if(folderName != null){
			lockPath = path + File.separator + folderName;
			File file = new File(lockPath);
			if(!file.exists()){
				file.mkdir();
			}		
		}
		try {
			while ((zipEntry = inputStream.getNextEntry()) != null) {
				if (zipEntry.isDirectory()) {
					String name = zipEntry.getName();
					name = name.substring(0, name.length() - 1);
					File file = new File(lockPath + File.separator + name);
					file.mkdir();
				} else {
					File file = new File(lockPath + File.separator
							+ zipEntry.getName());
					file.createNewFile();
					outputStream = new FileOutputStream(file);
					// 普通解压缩文件
					int b;
					while ((b = inputStream.read()) != -1) {
						outputStream.write(b);
					}
				}
			}
		} catch (IOException e) {
			logger.error(e.getMessage(),e);
			throw e;
		} finally {
			if(outputStream != null){
				outputStream.close();
			}
			if(inputStream != null){
				inputStream.close();
			}
			
		}
	}

	public static void main(String[] args) {
		ZipUtil.compress2("C:/rfp/file/jasper/201410", "C:/rfp/file/jasper.zip");
	}
}
